﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entity.Car_Rental;
using Entity.CommonEnums;

namespace Data.Car_Rental
{
    /// <summary>
    /// 扩展方法
    /// </summary>
    public static class AreaExtension
    {
        /// <summary>
        /// 根据ID得到实体
        /// </summary>
        /// <param name="linq"></param>
        /// <param name="codeID"></param>
        /// <returns></returns>
        public static Area GetAddressByCodeID(this IQueryable<Area> linq, int codeID)
        {
            return linq.FirstOrDefault(i => i.CodeID == codeID);
        }

        /// <summary>
        /// 返回指定ID长度的结果集
        /// </summary>
        /// <param name="linq"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static IQueryable<Area> GetAddressByCodeLength(this IQueryable<Area> linq, int length)
        {
            return linq.Where(i => i.CodeID.ToString().Length == length);
        }
    }
    public class AreaRepository : Car_RentalRepositoryBase, IAreaRepository
    {
        #region 静态树结构，每1分钟去获一下数据库
        static List<Area> categoryList = null;
        static AreaRepository categoryRepository = new AreaRepository();
        static System.Timers.Timer sysTimer = new System.Timers.Timer(60000000);
        static AreaRepository()
        {
            Reload();//第一次加载
            sysTimer.AutoReset = true;
            sysTimer.Enabled = true;
            sysTimer.Elapsed += new System.Timers.ElapsedEventHandler(sysTimer_Elapsed);
            sysTimer.Start();
        }

        /// <summary>
        /// 被订阅了Elapsed事件的方法,每隔一段时间去重新获取数据列表
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void sysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Reload();
        }

        /// <summary>
        /// 手动重新从数据库得到最新数据
        /// </summary>
        public static void Reload()
        {
            categoryList = categoryRepository.GetAreas().OrderBy(i => i.CodeID).ToList();
        }
        /// <summary>
        /// 分类树结构
        /// </summary>
        /// <returns>项目分类列表</returns>
        public static Area GetTree()
        {
            Area root = new Area();
            try
            {
                root = categoryList.Single(item => item.CodeID.Equals(0));//获取跟节点
                GetSublCategories(root);
            }
            catch (Exception ex)
            {
                throw new Exception("无效根节点" + ex.ToString());
            }
            return root;
        }


        /// <summary>
        /// 根据父对象，找到子孙树
        /// </summary>
        /// <param name="father">父对象</param>
        static void GetSublCategories(Area father)
        {
            father.Sons = categoryList.Where(item =>
                item.ParentID.Equals(father.CodeID) && item.CodeID != 0).ToList();
            father.Sons.ToList().ForEach(item =>
            {
                item.Father = father;
                GetSublCategories(item);
            });

        }
        #endregion

        public IQueryable<Area> GetAreas()
        {
            return this.GetModel().Select(i => new Area_Ext
            {
                CodeID = i.CodeID,
                Name = i.Name,
                ParentID = i.ParentID,
                Status = i.Status,
            });
        }
        /// <summary>
        /// 得到树型结果集
        /// </summary>
        /// <returns></returns>
        public IQueryable<Area> GetAreasForTree()
        {
            var linq = from data in this.GetModel()
                       join data2 in this.GetModel() on data.ParentID equals data2.CodeID into father
                       join data3 in this.GetModel() on data.CodeID equals data3.ParentID into list
                       select new Area_Ext
                       {
                           CodeID = data.CodeID,
                           Name = data.Name,
                           ParentID = data.ParentID,
                           Status = data.Status,
                           Father = father.FirstOrDefault() == null ? new Area { CodeID = 0, Name = "根" } : father.FirstOrDefault(),
                           Sons = list,

                       };
            return linq;
        }

        public IQueryable<Area> GetModelByParentId(int parentid)
        {
            return this.GetAreas().Where(i => i.ParentID.Equals(parentid));
        }

        #region 地区

        public List<Area> GetChildrenAddressByName(string name, int length)
        {
            Area area = this.GetModel().Where(a => a.Name == name && a.CodeID.ToString().Length == length).FirstOrDefault();
            if (area != null)
            {
                List<Area> data = this.GetModel().Where(a => a.ParentID == area.CodeID).ToList();
                return data;
            }
            else
            {
                return new List<Area>();
            }
        }

        public List<Area> GetChildrenAddressByCodeID(int codeid)
        {
            return this.GetModel().Where(a => a.ParentID == codeid).ToList();
        }

        public Area GetAddressByName(string name, int length)
        {
            Area linq = this.GetModel().Where(a => a.Name == name && a.CodeID.ToString().Length == length).FirstOrDefault();
            if (linq == null)
                linq = this.GetModel().Where(a => a.CodeID.ToString().Length == length).FirstOrDefault();
            return linq;
        }

        public Area GetAddressByCodeID(int codeid)
        {
            return this.GetModel().Where(a => a.CodeID == codeid).FirstOrDefault();
        }

        #region IAreaServices 成员

        public Area GetCommon_AreaTree()
        {
            return GetTree();
        }

        public Entity.PagedList<Area> GetCommon_Area(Entity.VPredication vp, Entity.PagingParam pp)
        {
            var linq = GetAreasForTree();
            if (vp.ContainsKey("Name"))
                linq = linq.Where(i => i.Name.Contains(vp["Name"].ToString()));
            return new Entity.PagedList<Area>(linq, pp.PageIndex, pp.PageSize);
        }

        public Entity.VMessage AddCommon_Area(Area entity)
        {
            Entity.VMessage VMessage = new Entity.VMessage();
            try
            {
                entity.Status = (int)Status.Normal;

                if (entity.ParentID.ToString().Length == 1) //添加省
                {
                    entity.CodeID = GetModel().Where(i => i.CodeID.ToString().Length == 2).Max(i => i.CodeID) + 1;
                }
                if (entity.ParentID.ToString().Length == 2) //添加省下的市
                {
                    var test = GetModel().Where(i => i.CodeID.ToString().Length == 4 && i.CodeID.ToString().Substring(0, 2) == entity.ParentID.ToString());
                    entity.CodeID = test != null && test.Count() > 0
                        ? test.Max(i => i.CodeID) + 1
                        : Convert.ToInt32(entity.ParentID.ToString() + "01");
                }
                if (entity.ParentID.ToString().Length == 4) //添加市下的县
                {
                    var test = GetModel().Where(i => i.CodeID.ToString().Length == 6 && i.CodeID.ToString().Substring(0, 4) == entity.ParentID.ToString());
                    entity.CodeID = test != null && test.Count() > 0
                        ? test.Max(i => i.CodeID) + 1
                        : Convert.ToInt32(entity.ParentID.ToString() + "01");
                }
                Insert(entity);
                Reload();
                VMessage.IsComplete = true;
            }
            catch (Exception)
            {
                VMessage.IsComplete = false;
                throw;
            }
            return VMessage;

        }

        public Entity.VMessage EditCommon_Area(Area entity)
        {
            Entity.VMessage VMessage = new Entity.VMessage();
            try
            {
                Update(entity);
                Reload();
                VMessage.IsComplete = true;
            }
            catch (Exception)
            {
                VMessage.IsComplete = false;
                throw;
            }
            return VMessage;

        }

        public bool DeleteCommon_Area(Area entity)
        {
            bool flag = false;
            try
            {
                Delete(entity);
                Reload();
                flag = true;
            }
            catch (Exception)
            {

                throw;
            }
            return flag;
        }

        public Area GetCommon_Area(int codeID)
        {
            return GetModel().FirstOrDefault(i => i.CodeID == codeID);
        }
        #endregion
        #endregion
        #region IRepository<Area> 成员

        public void Update(Area entity)
        {
            base.UpdateEntity(entity);
        }

        public void Update(IList<Area> list)
        {
            base.UpdateEntity(list.Cast<Entity.EntityBase>().ToList());
        }

        public void Insert(Area entity)
        {
            base.InsertEntity(entity);
        }

        public void Insert(IList<Area> list)
        {
            base.InsertEntity(list.Cast<Entity.EntityBase>().ToList());
        }

        public Area InsertGetIDENTITY(Area entity)
        {
            base.InsertEntity(entity);
            return this.Find(entity.PrimaryKey);
        }

        public void Delete(Area entity)
        {
            base.DeleteEntity(entity);
        }

        public void Delete(IList<Area> list)
        {
            base.DeleteEntity(list.Cast<Entity.EntityBase>().ToList());
        }

        public IQueryable<Area> GetModel()
        {
            return base.GetEntities<Area>();
        }

        public Area Find(params object[] keyValues)
        {
            return base.Find<Area>(keyValues);
        }

        #endregion
    }
}
